﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Meraz.Core.Model;
using Meraz.Core.Repositories;
using System.Text.RegularExpressions;

namespace Meraz.Core.Commands
{
    public interface ISaveStudyCommand<TEntity> { TEntity Study { get; set; } void Execute(); }
    public interface ISaveBlogStudyCommand : ISaveStudyCommand<BlogStudy> { }
    public interface ISaveTwitterStudyCommand : ISaveStudyCommand<TwitterStudy> { }
    public abstract class SaveStudyCommand<TEntity> : BaseCommand, ISaveStudyCommand<TEntity>
        where TEntity : Study
    {
        public IStudyRepository<TEntity> Repository { get; set; }
        public TEntity Study { get; set; }

        public void Execute()
        {
            if (Study == null)
                throw new ApplicationException("Study cannot be null");

            if (string.IsNullOrWhiteSpace(Study.Name))
                throw new ApplicationException("Study must have a Name.");

            if (!ValidateName(Study.Name))
                throw new ApplicationException("Study Name must have letters and/or numbers");

            Study existing = Repository.GetById(Study.ID);

            if (existing == null)
            {
                existing = Repository.GetByName(Study.Name);
                if (existing != null)
                {
                    Study.ID = existing.ID;
                }
            }
            //set defaults
            if (Study.StatusType == StatusType.Undefined)
                Study.StatusType = StatusType.Active;
            if (Study.StartDate == null || Study.StartDate == DateTime.MinValue)
                Study.StartDate = DateTime.Now;
            if (Study.EndDate == null || Study.EndDate == DateTime.MinValue)
                Study.EndDate = DateTime.Now;

            if (existing == null)
            {
                //we still haven't found it
                Repository.Add(Study);
            }
            else
            {
                existing.Name = Study.Name;
                existing.Status = Study.Status;
                existing.StartDate = Study.StartDate;
                existing.EndDate = Study.EndDate;
            }

            SaveChildren();
            Commit();
        }

        bool ValidateName(string name)
        {
            return Regex.IsMatch(name, @"\w+", RegexOptions.CultureInvariant);
        }
    
        protected abstract void SaveChildren();
    }

    public class SaveBlogStudyCommand : SaveStudyCommand<BlogStudy>, ISaveBlogStudyCommand
    {
        public IBlogStudyRepository BlogStudyRepository { get; set; }
        public SaveBlogStudyCommand(IBlogStudyRepository blogStudyRepository)
        {
            Repository = blogStudyRepository ?? new BlogStudyRepository();
        }
        protected override void SaveChildren()
        {
        }
    }
    public class SaveTwitterStudyCommand : SaveStudyCommand<TwitterStudy>, ISaveTwitterStudyCommand
    {

        public SaveTwitterStudyCommand(ITwitterStudyRepository twitterStudyRepository)
        {
            Repository = twitterStudyRepository ?? new TwitterStudyRepository();
        }
        protected override void SaveChildren()
        {
        }
    }
}
